#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/crc32.h>
#include <linux/miscdevice.h>
#include "simple_mem.h"

// 设备数据结构
struct simple_mem_dev {
    struct miscdevice miscdev; // 杂项设备
    struct mutex lock;         // 互斥锁
    char *buffer;             // 内存缓冲区
    size_t size;               // 缓冲区大小
};

static struct simple_mem_dev *simple_dev;

// 文件打开操作
static int simple_mem_open(struct inode *inode, struct file *filp)
{
    filp->private_data = simple_dev;
    return 0;
}

// 文件读取操作
static ssize_t simple_mem_read(struct file *filp, char __user *buf, 
                              size_t count, loff_t *f_pos)
{
    struct simple_mem_dev *dev = filp->private_data;
    ssize_t ret = 0;
    
    mutex_lock(&dev->lock);
    
    if (*f_pos >= dev->size) {
        ret = 0;
        goto out;
    }
    
    if (*f_pos + count > dev->size)
        count = dev->size - *f_pos;
    
    if (copy_to_user(buf, dev->buffer + *f_pos, count)) {
        ret = -EFAULT;
        goto out;
    }
    
    *f_pos += count;
    ret = count;

out:
    mutex_unlock(&dev->lock);
    return ret;
}

// 文件写入操作
static ssize_t simple_mem_write(struct file *filp, const char __user *buf, 
                               size_t count, loff_t *f_pos)
{
    struct simple_mem_dev *dev = filp->private_data;
    ssize_t ret = 0;
    
    mutex_lock(&dev->lock);
    
    if (*f_pos >= dev->size) {
        ret = -EFBIG; // 超出文件大小
        goto out;
    }
    
    if (*f_pos + count > dev->size)
        count = dev->size - *f_pos;
    
    if (copy_from_user(dev->buffer + *f_pos, buf, count)) {
        ret = -EFAULT;
        goto out;
    }
    
    *f_pos += count;
    ret = count;

out:
    mutex_unlock(&dev->lock);
    return ret;
}

// IOCTL控制操作
static long simple_mem_ioctl(struct file *filp, unsigned int cmd, 
                            unsigned long arg)
{
    struct simple_mem_dev *dev = filp->private_data;
    unsigned int crc = 0;
    unsigned int new_size;
    
    switch (cmd) {
    case SIMPLE_MEM_GET_CRC:
        mutex_lock(&dev->lock);
        // 计算整个缓冲区的CRC32哈希值
        crc = crc32(0, dev->buffer, dev->size);
        mutex_unlock(&dev->lock);
        
        if (copy_to_user((unsigned int __user *)arg, &crc, sizeof(crc)))
            return -EFAULT;
        break;
        
    case SIMPLE_MEM_SET_SIZE:
        if (copy_from_user(&new_size, (unsigned int __user *)arg, sizeof(new_size)))
            return -EFAULT;
        
        if (new_size > (1024 * 1024)) // 限制最大1MB
            return -EINVAL;
        
        mutex_lock(&dev->lock);
        
        // 释放旧内存，申请新内存
        kfree(dev->buffer);
        dev->buffer = kmalloc(new_size, GFP_KERNEL);
        if (!dev->buffer) {
            mutex_unlock(&dev->lock);
            return -ENOMEM;
        }
        
        dev->size = new_size;
        memset(dev->buffer, 0, dev->size); // 清零新内存
        mutex_unlock(&dev->lock);
        break;
        
    default:
        return -ENOTTY; // 不支持的命令
    }
    
    return 0;
}

// 文件操作结构
static const struct file_operations simple_mem_fops = {
    .owner = THIS_MODULE,
    .open = simple_mem_open,
    .read = simple_mem_read,
    .write = simple_mem_write,
    .unlocked_ioctl = simple_mem_ioctl,
};

// 模块初始化
static int __init simple_mem_init(void)
{
    int ret;
    
    // 分配设备结构
    simple_dev = kzalloc(sizeof(struct simple_mem_dev), GFP_KERNEL);
    if (!simple_dev)
        return -ENOMEM;
    
    // 初始化互斥锁
    mutex_init(&simple_dev->lock);
    
    // 分配内存缓冲区
    simple_dev->buffer = kmalloc(DEFAULT_MEM_SIZE, GFP_KERNEL);
    if (!simple_dev->buffer) {
        ret = -ENOMEM;
        goto free_dev;
    }
    simple_dev->size = DEFAULT_MEM_SIZE;
    memset(simple_dev->buffer, 0, DEFAULT_MEM_SIZE); // 初始化为0
    
    // 设置杂项设备
    simple_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
    simple_dev->miscdev.name = DEVICE_NAME;
    simple_dev->miscdev.fops = &simple_mem_fops;
    simple_dev->miscdev.mode = 0666; // 所有用户可读写
    
    // 注册设备
    ret = misc_register(&simple_dev->miscdev);
    if (ret) {
        pr_err("Failed to register misc device\n");
        goto free_buffer;
    }
    
    pr_info("Simple memory device registered with %u bytes buffer\n", DEFAULT_MEM_SIZE);
    return 0;

free_buffer:
    kfree(simple_dev->buffer);
free_dev:
    kfree(simple_dev);
    return ret;
}

// 模块退出
static void __exit simple_mem_exit(void)
{
    misc_deregister(&simple_dev->miscdev);
    kfree(simple_dev->buffer);
    mutex_destroy(&simple_dev->lock);
    kfree(simple_dev);
    pr_info("Simple memory device unregistered\n");
}

module_init(simple_mem_init);
module_exit(simple_mem_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple memory device driver with CRC32 checksum");
